const puppeteer = require('puppeteer');
const path = require('path');
const fs = require('fs');

const {sleep} = require('./utils');

class Skeleton {
  constructor(options) {
    this.options = options;
    this.browser = null;
  }

  async initialize(){
    this.browser = await puppeteer.launch({headless: true});//打开一个浏览器
  }

  async newPage(){
    const {device} = this.options;
    const page = await this.browser.newPage()
    await page.emulate(puppeteer.devices[device]); //这里是模拟iphone6访问效果
    return page;
  }

  async genHTML(url){
    const page = await this.newPage();
    const response = await page.goto(url,{waitUntil:'networkidle2'})
    if (response && !response.ok()) {
      throw new Error(`${response.status} on ${url}`);
    }

    //创建骨架屏
    await this.makeSkeleton(page);
    const {html, styles} = await page.evaluate(() => Skeleton.getHtmlAndStyle());
    const result = `
      <style>${styles.join('\n')}</style>
      ${html}
    `;

    return result;
  }

  async destroy(){
    if(this.browser){
      await this.browser.close();
      this.browser = null;
    }
  }

  async makeSkeleton(page) {
    const {defer = 800} = this.options;
    const scriptContent = await fs.readFileSync(path.resolve(__dirname, 'skeletonScript.js'), 'utf8');

    //向页面内注入此脚本, 会往全局对象上注入一个 window.Skeleton {genSkeleton, getHtmlAndStyle}
    await page.addScriptTag({content: scriptContent})
    await sleep(defer);

    //创建骨架屏dom结构
    await page.evaluate(options => { //会在页面中执行此函数
      Skeleton.genSkeleton(options);
    },this.options);
  }
}

module.exports = Skeleton;
